package com;


import cn.hutool.core.date.StopWatch;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 比较 stream parallelStream HashSet 的去重对象速度
 *
 * @author yunlongn
 */
public class Test02 {

    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Test02 areaDO = (Test02) o;
        return Objects.equals(id, areaDO.id);
    }

        public static void main(String[] args) {
        List<Test02> sysAreaAll =  new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            Test02 test02 = new Test02();
            test02.setId(1L);
            sysAreaAll.add(test02);
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("stream");
        List<Test02> dbList2 = sysAreaAll.stream().filter(distinctByKey(Test02::getId)).collect(Collectors.toList());
        stopWatch.stop();
        stopWatch.start("parallelStream");
        List<Test02> dbList3 = sysAreaAll.parallelStream().filter(distinctByKey(Test02::getId)).collect(Collectors.toList());
        stopWatch.stop();
        // HashSet是根据对象 equals 来去重数据的。 所以他不会对 HashMap做增加删除操作。所以少了这一步骤。不过数据大的情况下还是会比其他慢
        stopWatch.start("HashSet");
        HashSet<Test02> Test02List = new HashSet<>(sysAreaAll);
        stopWatch.stop();

        stopWatch.start("ArrayList");
        List<Test02> Test02List2 = new ArrayList<>(new HashSet<>(sysAreaAll));
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
        System.out.println(dbList3);
    }
   
    
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> seen = new ConcurrentHashMap<>();
        return t -> {
            return seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
        };
    }
}

